use crate::capi::{
    iot_err_code_e, iot_err_code_e_RC_FAIL, iot_err_code_e_RC_INVALID_PARAMS, iot_err_code_e_RC_OK,
};
use crate::utils::{calc_d_access_token, DownloadContext, DownloadFile};
use alloc::borrow::ToOwned;
use core::ffi::{c_uint, c_void};
use embed_std::libc::{c_char, c_longlong};
use embed_std::util::cstr_to_str;
use embed_std::{errorln, infoln};

#[no_mangle]
unsafe extern "C" fn download_file(
    url: *const c_char,
    filename: *const c_char,
    cb: Option<unsafe extern "C" fn(total: c_longlong, pos: c_longlong, args: *mut c_void)>,
    cb_args: *mut c_void,
) -> iot_err_code_e {
    if url.is_null() || filename.is_null() || cb.is_none() {
        return iot_err_code_e_RC_FAIL;
    }
    let r_url = cstr_to_str(url);
    let r_filename = cstr_to_str(filename);
    let c = DownloadContext { cb, args: cb_args };
    let mut ctx = DownloadFile::new(r_url.to_owned(), r_filename.to_owned());
    match ctx.start(&c) {
        Ok(_) => {
            infoln!("download {} to file {} ok", r_url, r_filename);
        }
        Err(e) => {
            errorln!("download {} to file {} failed {}", r_url, r_filename, e);
            return iot_err_code_e_RC_FAIL;
        }
    }
    iot_err_code_e_RC_OK
}

#[no_mangle]
pub fn gen_d_access_token(
    device_uid: *const c_char,
    secret: *const c_char,
    token: *mut c_char,
    token_len: c_uint,
) -> iot_err_code_e {
    if device_uid.is_null() || secret.is_null() || token.is_null() || token_len == 0 {
        return iot_err_code_e_RC_INVALID_PARAMS;
    }
    let r_device_uid = cstr_to_str(device_uid);
    let r_secret = cstr_to_str(secret);
    let tk = calc_d_access_token(r_device_uid, r_secret);
    if token_len < tk.len() as c_uint + 1 {
        errorln!(
            "token buffer {} is too small. expect {}",
            token_len,
            tk.len()
        );
        return iot_err_code_e_RC_INVALID_PARAMS;
    }
    unsafe {
        core::ptr::copy(tk.as_ptr() as *const c_char, token, tk.len());
        *token.offset(tk.len() as isize) = 0;
    }
    iot_err_code_e_RC_OK
}
